<?php

/**
 * Holds class Database
 *
 * @author Mark
 * @author daantimmer
 *
 * @package Library
 */

/**
 * Database accessing class
 *
 * @link http://www.php.net/pdo
 * @see PDO
 *
 * @author Mark
 * @author daantimmer
 */
class Database extends PDO {
	
	private static $queries = 0;
	
	/**
	 * Constructor
	 *
	 * @author Mark
	 * @author daantimmer
	 *
	 * @param string $dsn
	 * @param string $username (optional)
	 * @param string $password (optional)
	 * @param array $driverOptions (optional)
	 * @throws PDOException
	 * @return void
	 */
	public function __construct($dsn, $username = null, $password = null, array $driverOptions = array(), $only_full_group = true) {
		parent::__construct($dsn, $username, $password, $driverOptions);

		// Set attributes
		$this->setAttribute(self::ATTR_ERRMODE, self::ERRMODE_EXCEPTION);//exceptions
		$this->setAttribute(self::ATTR_DEFAULT_FETCH_MODE, self::FETCH_ASSOC);//index by name
		$this->setAttribute(self::ATTR_STATEMENT_CLASS, array('DBStatement'));//Set DBStatement class as PDOStatement

		// Configure MySQL
		if('mysql' == $this->getAttribute(self::ATTR_DRIVER_NAME)) {
			// Force queries to be buffered in MySQL
			$this->setAttribute(self::MYSQL_ATTR_USE_BUFFERED_QUERY, true);

			// Configure MySQL to act as a normal database
			// @link http://wiki.phpfreakz.nl/Werken_met_MySQL
			
			$only_full_group = ($only_full_group) ? "" : "ONLY_FULL_GROUP_BY,";
			try{
				if(version_compare("5.0.0",$this->getAttribute(PDO::ATTR_SERVER_VERSION),"<=")){
					//higher then mysql 5 version
					$this->exec("SET NAMES 'latin1', SESSION sql_mode = 'TRADITIONAL,{$only_full_group}NO_AUTO_VALUE_ON_ZERO,PIPES_AS_CONCAT'");
				}else{
					//lower then mysql 5 version, can not set TRADITIONAL mode
					$this->exec("SET NAMES 'latin1', SESSION sql_mode = '{$only_full_group}NO_AUTO_VALUE_ON_ZERO,PIPES_AS_CONCAT'");
				}
			}catch(PDOException $e){
				throw new PDOException('Cannot set SQL mode');
			}
			
//			if(false === $this->exec("SET NAMES 'utf8', SESSION sql_mode = 'TRADITIONAL,ONLY_FULL_GROUP_BY,NO_AUTO_VALUE_ON_ZERO,PIPES_AS_CONCAT'")) {
//				throw new PDOException('Cannot set SQL mode');
//			}
		}
	}
	
	/**
	 * Basic insert function.
	 *
	 * Extracts information from $obj, builds a query and executes (insert) the query.
	 * $ignoreNull param specifies to ignore columns with empty values
	 * $ignore specifies if the query should be an INSERT IGNORE INTO (true) or INSERT INTO (false)
	 * query
	 *
	 * @param mixed $obj the object to insert
	 * @param string $table table where to insert the object
	 * @param boolean $ignoreNull
	 * @param boolean $ignore
	 * @return boolean
	 */
	public function insert($obj,$table, $ignoreNull = true, $ignore = false){
		$fields = get_class_vars(get_class($obj));
		
		$collist = array();
		$parlist = array();
		$vallist = array();
		
		foreach($fields AS $var => $val){
			if(isset($obj->{$var}) || !$ignoreNull){
				$collist[] = "{$var}";
				$parlist[] = ":{$var}";
			}
		}
		
		if($ignoreNull){
			if(count($collist) < 1)
				throw new Exception("No values will be set, no columns defined.");
		}
		
		$collist = implode(",",$collist);
		$parlist = implode(",",$parlist);
		
		$ignore = (is_bool($ignore) && $ignore === true) ? "IGNORE " : "";
		$query	=	"INSERT {$ignore} INTO {$table}({$collist}) VALUES({$parlist})";
		
		$stmt = $this->prepare($query);
		
		foreach($fields AS $var => $val){
			if(isset($obj->{$var}) || !$ignoreNull){
				$stmt->bindParam(":{$var}", $obj->{$var});
			}
		}
		
		return $stmt->execute();
	}
	
	/**
	 * Custom prepare statement
	 *
	 * @see PDO::prepare
	 *
	 * @author daantimmer
	 *
	 * @param statment
	 * @param options[optional]
	 * @return DBStatement
	 */
	public function prepare ($statement, $options = array()) {
		Database::$queries++;
		return parent::prepare($statement,$options);
	}
	
	/**
	 * Returns amount of prepared statements.
	 *
	 * @author daantimmer
	 *
	 * @return int
	 */
	public static function getQueryCount(){
		return Database::$queries;
	}
}
